package com.vegetable.modules.service.inbound.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.constant.CommonConstant;
import com.vegetable.common.utils.Constant;
import com.vegetable.common.utils.Constant.StockFlowType;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.Query;
import com.vegetable.common.utils.R;
import com.vegetable.modules.entity.baseData.ProductSpec;
import com.vegetable.modules.entity.baseData.Products;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetailPack;
import com.vegetable.modules.entity.inbound.OrderCost;
import com.vegetable.modules.entity.inbound.OtherDelivery;
import com.vegetable.modules.entity.inbound.OtherDeliveryDetail;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.stock.to.StockFlowDTO;
import com.vegetable.modules.mapper.inbound.OtherDeliveryMapper;
import com.vegetable.modules.service.baseData.IProductSpecService;
import com.vegetable.modules.service.baseData.IProductsService;
import com.vegetable.modules.service.inbound.IAgentDeliveryDetailPackService;
import com.vegetable.modules.service.inbound.IOtherDeliveryDetailService;
import com.vegetable.modules.service.inbound.IOtherDeliveryService;
import com.vegetable.modules.service.stock.IStockFlowService;
import com.vegetable.modules.service.stock.IStockService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 其他入库表 服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-11
 */
@Slf4j
@Service
@AllArgsConstructor
public class OtherDeliveryServiceImpl extends ServiceImpl<OtherDeliveryMapper, OtherDelivery> implements IOtherDeliveryService {

    // 商品明细
    private IOtherDeliveryDetailService deliveryDetailService;

    // 产地商品
    private IProductsService productsService;

    // 商品规格
    private IProductSpecService specService;
    private IAgentDeliveryDetailPackService iAgentDeliveryDetailPackService;

    // 库存管理
    private IStockService stockService;
    private IStockFlowService stockFlowService;

    /**
     * 其他入库列表查询
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String docNo = (String)params.get("docNo");
        String startTime = (String)params.get("startTime");
        String endTime = (String)params.get("endTime");
        // 标题
        String title = (String)params.get("title");
        IPage<OtherDelivery> page = this.page(
                new Query<OtherDelivery>().getPage(params),
                new QueryWrapper<OtherDelivery>()
                        .between(StringUtils.isNotBlank(startTime), "order_time", startTime, endTime)
                        .like(StringUtils.isNotBlank(title),"title", title)
                        .like(StringUtils.isNotBlank(docNo),"doc_no", docNo)
                        .orderByDesc("create_time")
        );

        return new PageUtils(page);
    }

    /**
     * 详情其他入库
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    public R detailOtherDelivery(Long id) {
        OtherDelivery otherDelivery = baseMapper.selectById(id);
        if (otherDelivery == null){
            return R.fail("订单不存在");
        }
        // 查询原订单的商品
        QueryWrapper<OtherDeliveryDetail> detailQuery = new QueryWrapper();
        detailQuery.eq("delivery_id", otherDelivery.getId());
        List<OtherDeliveryDetail> details = deliveryDetailService.getBaseMapper().selectList(detailQuery);
        if (CollectionUtils.isNotEmpty(details)){
            for (OtherDeliveryDetail detail:details) {
                List<AgentDeliveryDetailPack> packs = iAgentDeliveryDetailPackService.selectByDetailId(detail.getId());
                detail.setAutoCosts(packs);
            }
            otherDelivery.setCommodities(details);
        }
        List<StockFlowDTO> flows = stockFlowService.queryOutFlowByOrderNo(otherDelivery.getDocNo(), otherDelivery.getId());
        otherDelivery.setStockFlows(flows);
        List<Stock> stocks = stockService.queryStock(otherDelivery.getDocNo());
        otherDelivery.setStocks(stocks);
        return R.data(otherDelivery);
    }

    /**
     * 新增其他入库
     * @param otherDelivery null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveOtherDelivery(OtherDelivery otherDelivery) throws Exception {
        // 新增其他入库主表
        StringBuilder commodityNames = new StringBuilder();
        if (CollectionUtils.isEmpty(otherDelivery.getCommodities())){
            throw new Exception("商品列表不能为空");
        }
        Integer number = 0;
        BigDecimal weight = BigDecimal.ZERO;
        shareCost(otherDelivery);
        for (OtherDeliveryDetail deliveryDetail: otherDelivery.getCommodities()) {
            commodityNames.append(deliveryDetail.getCommodityName()).append("|");
            number = number+deliveryDetail.getNumber();
            weight = weight.add(deliveryDetail.getWeight());
        }

        otherDelivery.setNumber(number);
        otherDelivery.setWeight(weight);
        otherDelivery.setCommodityNames(commodityNames.toString());
        otherDelivery.setOrderTime(new Date());
        if (otherDelivery.getId() == null){
            otherDelivery.setDocNo(CommonConstant.QTRK+ baseMapper.getNextCode());
            save(otherDelivery);
        }else {
            updateById(otherDelivery);
            // 删除其他费用，商品信息，已经商品下的信息
            deleteMethod(otherDelivery);
        }

        // 其他入库主键
        Long mainId = otherDelivery.getId();
        // 保存订单下明细
        List<OtherDeliveryDetail> commodities =  otherDelivery.getCommodities();
        for (OtherDeliveryDetail deliveryDetail: commodities) {
            deliveryDetail.setId(null);
            deliveryDetail.setDeliveryId(mainId);
        }
        deliveryDetailService.saveBatch(commodities);
        for (OtherDeliveryDetail deliveryDetail: commodities) {
            if (CollectionUtils.isNotEmpty(deliveryDetail.getAutoCosts())){
                List<AgentDeliveryDetailPack> autoCosts = deliveryDetail.getAutoCosts();
                for (AgentDeliveryDetailPack autoCost: autoCosts) {
                    autoCost.setId(null);
                    autoCost.setDetailId(deliveryDetail.getId());
                }
                iAgentDeliveryDetailPackService.saveBatch(autoCosts);
            }
        }

        return R.data(mainId);
    }

    private void saveDetailInfo(Long mainId, OtherDelivery agentDelivery){

    }

    private void shareCost(OtherDelivery agentDelivery) {
        if (CollectionUtils.isNotEmpty(agentDelivery.getCosts())) {
            agentDelivery.getCommodities().forEach(detail -> {
                detail.setCosts(new ArrayList<>());
            });
            for (OrderCost cost : agentDelivery.getCosts()) {
                if (CollectionUtil.isNotEmpty(cost.getSerialNumberList())){
                    Map<Long, BigDecimal> numberMap = cost.getSerialNumberList();
                    // 参与分摊的商品重量合计
                    BigDecimal weightTotal = agentDelivery.getCommodities().stream().
                            filter(s -> numberMap.containsKey(s.getCommodityId())).map(s -> s.getWeight()).
                            reduce(BigDecimal.ZERO, BigDecimal::add);
                    if(NumberUtil.equals(weightTotal, BigDecimal.ZERO)){
                        log.error("异常数据分摊{}", JSONObject.toJSONString(agentDelivery));
                        return;
                    }
                    // 均摊的单价费用
                    BigDecimal unitMoney = cost.getMoney().divide(weightTotal, 6, RoundingMode.HALF_UP);
                    for (OtherDeliveryDetail deliveryDetail: agentDelivery.getCommodities()) {
                        // 存在
                        if (numberMap.containsKey(deliveryDetail.getCommodityId())){
                            // 单价*重量= 均摊的金额
                            BigDecimal multiply = unitMoney.multiply(deliveryDetail.getWeight());
//                            BigDecimal money = deliveryDetail.getMoney();
//                            money = money.add(multiply);
//                            deliveryDetail.setMoney(money);
                            // 重新组装商品的其他费用
                            if (CollectionUtils.isNotEmpty(deliveryDetail.getCosts())){
                                OrderCost cost1 = new OrderCost();
                                cost1.setCostClauseId(cost.getCostClauseId());
                                cost1.setCostClauseName(cost.getCostClauseName());
                                cost1.setMoney(multiply);
                                deliveryDetail.getCosts().add(cost1);
                            }else {
                                List<OrderCost> detailCosts = new ArrayList<>();
                                OrderCost cost1 = new OrderCost();
                                cost1.setCostClauseId(cost.getCostClauseId());
                                cost1.setCostClauseName(cost.getCostClauseName());
                                cost1.setMoney(multiply);
                                detailCosts.add(cost1);
                                deliveryDetail.setCosts(detailCosts);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 提交其他入库
     * @param otherDelivery null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submitOtherDelivery(OtherDelivery otherDelivery) throws Exception {
        // 新增其他入库主表
        otherDelivery.setState(1);
        saveOtherDelivery(otherDelivery);
        // 生成库存
        inStock(otherDelivery);
        return R.data(otherDelivery.getId());
    }


    /**
     * 其他收货-入库逻辑
     * @param otherDelivery
     */
    private void inStock(OtherDelivery otherDelivery){
        for (OtherDeliveryDetail detail : otherDelivery.getCommodities()) {
            // 根据商品id查询商品
            Products products = productsService.getById(detail.getCommodityId());
            if (products == null){
                continue;
            }
            String specsName = null;
                if (ObjectUtil.isNotNull(detail.getSpecsId())){
                    ProductSpec productSpec = specService.getById(detail.getSpecsId());
                    specsName = productSpec.getName();
                }
                Date orderTime = otherDelivery.getOrderTime();
                String docNo = otherDelivery.getDocNo();
                // 计算成本
                String agentName = "";
                String packageCost = "";
            BigDecimal add = calOrderCost(detail);
            // 录入一号仓库的货物的货款
            BigDecimal inMoney = add;
                stockService.inStock(orderTime, inMoney, products, detail.getSpecsId(), specsName, detail.getNumber(), detail.getWeight(), StockFlowType.OTHER_IN.getValue(), Constant.WAREHOUSE_ID, Constant.WAREHOUSE_NAME, agentName, packageCost, docNo, otherDelivery.getId(), detail.getId(), detail.getUnitPrice());
//            }
        }
    }
    private BigDecimal calOrderCost(OtherDeliveryDetail detail) {
        BigDecimal otherCost = BigDecimal.ZERO;
        // 商品其他费用
        List<OrderCost> orderCosts = detail.getCosts();
        if(CollectionUtil.isNotEmpty(orderCosts)){
            for(OrderCost oc : orderCosts){
                otherCost = NumberUtil.add(otherCost, oc.getMoney());
            }
        }
        //成本金额 = 蔬菜金额 + 其他金额
        BigDecimal add = NumberUtil.add(detail.getGoodsMoney(), otherCost);
        return add;
    }
    /**
     * 删除其他入库
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteOtherDelivery(Long id) throws Exception {
        OtherDelivery otherDelivery = baseMapper.selectById(id);
        if (otherDelivery == null){
            throw new Exception("订单不存在");
        }
//        if (otherDelivery.getState().intValue() != 0){
//            throw new Exception("订单已入库不允许删除");
//        }
        baseMapper.deleteById(id);
        deleteMethod(otherDelivery);
        // 释放库存
        stockService.releaseStock(otherDelivery.getDocNo());
        return R.status(true);
    }

    /**
     * 删除主方法
     * @param otherDelivery
     * @return
     */
    private R deleteMethod(OtherDelivery otherDelivery) throws Exception {
        // 删除原订单的商品
        QueryWrapper<OtherDeliveryDetail> detailQuery = new QueryWrapper();
        detailQuery.eq("delivery_id", otherDelivery.getId());
        List<OtherDeliveryDetail> details = deliveryDetailService.getBaseMapper().selectList(detailQuery);
        if (CollectionUtils.isNotEmpty(details)){
            // 订单下商品的id集合
            List<Long> detailIds = details.stream().map(OtherDeliveryDetail::getId).collect(Collectors.toList());
            log.info("删除订单下的商品列表:{}", JSON.toJSONString(detailIds));
            QueryWrapper<OtherDeliveryDetail> detailQueryWrapper = new QueryWrapper();
            detailQueryWrapper.eq("delivery_id", otherDelivery.getId());
            deliveryDetailService.getBaseMapper().delete(detailQueryWrapper);
            // 删除订单对应的包装
            iAgentDeliveryDetailPackService.deleteByDetailId(detailIds, 0);
        }
        return R.status(true);
    }
}
